package com.kin.bitmapcatching;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.http.AndroidHttpClient;
import android.os.AsyncTask;
import android.text.TextUtils;
import android.util.Log;
import android.widget.ImageView;

import com.kin.bitmapcatching.DisplayBitmap.ObserveCatching;

public class ImageDownloader
{
	private Context  mContext;
	private ObserveCatching mObserver;
	
	public ImageDownloader(Context context,ObserveCatching observer)
	{
		mContext = context;
		mObserver = observer;
	}
	
    public void download(String url, ImageView imageView) {
        BitmapDownloaderTask task = new BitmapDownloaderTask(imageView,mContext);
        task.execute(url);
    }
    
    public static Bitmap downloadAvatar(final String avatarUrl) {
        // If there is no avatar, we're done
        if (TextUtils.isEmpty(avatarUrl)) {
            return null;
        }

        try {
            Log.i("Image Downloader", "Downloading avatar: " + avatarUrl);
            // Request the avatar image from the server, and create a bitmap
            // object from the stream we get back.
            URL url = new URL(avatarUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.connect();
            try {
                final BitmapFactory.Options options = new BitmapFactory.Options();
                final Bitmap avatar = BitmapFactory.decodeStream(connection.getInputStream(),
                        null, options);
                if (avatar == null) return null;

                // Take the image we received from the server, whatever format it
                // happens to be in, and convert it to a JPEG image. Note: we're
                // not resizing the avatar - we assume that the image we get from
                // the server is a reasonable size...
                Log.i("Image Downloader", "Converting avatar to JPEG");
                ByteArrayOutputStream convertStream = new ByteArrayOutputStream(
                        avatar.getWidth() * avatar.getHeight() * 4);
                avatar.compress(Bitmap.CompressFormat.JPEG, 95, convertStream);
                convertStream.flush();
                convertStream.close();
                // On pre-Honeycomb systems, it's important to call recycle on bitmaps
//                avatar.recycle();
//                return convertStream.toByteArray();
                return avatar;
            } finally {
                connection.disconnect();
            }
        } catch (MalformedURLException muex) {
            // A bad URL - nothing we can really do about it here...
            Log.e("Image Downloader", "Malformed avatar URL: " + avatarUrl);
        } catch (IOException ioex) {
            // If we're unable to download the avatar, it's a bummer but not the
            // end of the world. We'll try to get it next time we sync.
            Log.e("Image Downloader", "Failed to download user avatar: " + avatarUrl);
        }
        return null;
    }
    
    static Bitmap downloadBitmap(String url) {
         final AndroidHttpClient client = AndroidHttpClient.newInstance("Android");
         final HttpGet getRequest = new HttpGet(url);

        try {
            HttpResponse response = client.execute(getRequest);
            final int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != HttpStatus.SC_OK) { 
                Log.w("ImageDownloader", "Error " + statusCode + " while retrieving bitmap from " + url); 
                return null;
            }
            
            final HttpEntity entity = response.getEntity();
            if (entity != null) {
                InputStream inputStream = null;
                try {
                    inputStream = entity.getContent(); 
                    final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                    return bitmap;
                } finally {
                    if (inputStream != null) { 
                        inputStream.close();  
                    }
                    entity.consumeContent();
                }
            }
        } catch (Exception e) {
            // Could provide a more explicit error message for IOException or IllegalStateException
            getRequest.abort();
        } finally {
            if (client != null) {
                client.close();
            }
        }            
        return null;
    }
    
    public class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap>{
    	
    	private final WeakReference imageViewReference;
    	public String fileImageUrl ;
    	private Context mContext;
    	
    	public BitmapDownloaderTask(ImageView imageView,Context context)
    	{
    		imageViewReference = new WeakReference(imageView);
    		mContext = context;
    	}

    	
    	@Override
    	protected Bitmap doInBackground(String... params)
    	{
    		// TODO Auto-generated method stub
    		fileImageUrl = params[0];
    		String key = String.valueOf(fileImageUrl);
    		Bitmap result = mObserver.getBitmapFromDiskCache(key);
    		if (result == null)
    		{
    			result = downloadAvatar(fileImageUrl);
    			mObserver.addBitmapToMemCache(String.valueOf(fileImageUrl), result);
    		}	
    		
    		return result;
    	}
    	
    	@Override
    	protected void onPostExecute(Bitmap result)
    	{
    		// TODO Auto-generated method stub
    		if (isCancelled())
    		{
    			result =  null;
    		}
    		if (imageViewReference != null && result !=null)
    		{
    			final ImageView imageView = (ImageView) imageViewReference.get();
    			final BitmapDownloaderTask task = getBitmapWorkerTask(imageView);
    			if (this == task && imageView!=null)
    			{
    				imageView.setImageBitmap(result);
    			}
    		}
    	}
    }
    
	public static boolean cancelPotentialWork(String fileName, ImageView imageView)
	{
		final BitmapDownloaderTask task = getBitmapWorkerTask(imageView);
		if (task != null)
		{
			final String fileNameOfTask = task.fileImageUrl;
			if (fileNameOfTask == null)
			{
				task.cancel(true);
			}
			else if (fileNameOfTask.equals(fileName))
			{
				// The same work is already in progress
				return false;
			}
			else
			{
				// Cancel previous task
				task.cancel(true);
			}
		}
		// No task associated with the ImageView, or an existing task was cancelled
		return true;
	}

	public static BitmapDownloaderTask getBitmapWorkerTask(ImageView imageView)
	{
		if (imageView != null)
		{
			final Drawable drawable = imageView.getDrawable();
			if (drawable instanceof AsyncDownloadDrawable)
			{
				final AsyncDownloadDrawable asyncDrawable = (AsyncDownloadDrawable) drawable;
				return asyncDrawable.getBitmapWorkerTask();
			}
		}
		return null;
	}

	public static class AsyncDownloadDrawable extends BitmapDrawable
	{
		private final WeakReference bitmapWorkerTaskReference;
		public AsyncDownloadDrawable(Resources res, Bitmap bitmap, BitmapDownloaderTask bitmapWorkerTask)
		{
			super(res, bitmap);
			bitmapWorkerTaskReference = new WeakReference(bitmapWorkerTask);
		}

		public BitmapDownloaderTask getBitmapWorkerTask()
		{
			return (BitmapDownloaderTask) bitmapWorkerTaskReference.get();
		}
	}

}
